// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "eventreceiver.h"
#include "common/common.h"
#include "copilot.h"
#include "codegeexmanager.h"
#include "services/project/projectservice.h"

#include <QMenu>

CodeGeeXReceiver::CodeGeeXReceiver(QObject *parent)
    : dpf::EventHandler(parent), dpf::AutoEventHandlerRegister<CodeGeeXReceiver>()
{
    using namespace std::placeholders;
    eventHandleMap.insert(editor.contextMenu.name, std::bind(&CodeGeeXReceiver::processContextMenuEvent, this, _1));
    eventHandleMap.insert(editor.selectionChanged.name, std::bind(&CodeGeeXReceiver::processSelectionChangedEvent, this, _1));
    eventHandleMap.insert(notifyManager.actionInvoked.name, std::bind(&CodeGeeXReceiver::processActionInvokedEvent, this, _1));
    eventHandleMap.insert(project.openProject.name, std::bind(&CodeGeeXReceiver::processOpenProjectEvent, this, _1));
    eventHandleMap.insert(uiController.switchToWidget.name, std::bind(&CodeGeeXReceiver::processSwitchToWidget, this, _1));
}

dpf::EventHandler::Type CodeGeeXReceiver::type()
{
    return dpf::EventHandler::Type::Async;
}

QStringList CodeGeeXReceiver::topics()
{
    return { T_MENU, editor.topic, notifyManager.topic, project.topic, uiController.topic };
}

void CodeGeeXReceiver::eventProcess(const dpf::Event &event)
{
    const auto &eventName = event.data().toString();
    if (!eventHandleMap.contains(eventName))
        return;

    eventHandleMap[eventName](event);
}

void CodeGeeXReceiver::processContextMenuEvent(const dpf::Event &event)
{
    QMenu *contextMenu = event.property("menu").value<QMenu *>();
    if (!contextMenu)
        return;

    QMetaObject::invokeMethod(this, [contextMenu]() {
        contextMenu->addMenu(Copilot::instance()->getMenu());
    });
}

void CodeGeeXReceiver::processSelectionChangedEvent(const dpf::Event &event)
{
    QString fileName = event.property("fileName").toString();
    int lineFrom = event.property("lineFrom").toInt();
    int indexFrom = event.property("indexFrom").toInt();
    int lineTo = event.property("lineTo").toInt();
    int indexTo = event.property("indexTo").toInt();
    Copilot::instance()->handleSelectionChanged(fileName, lineFrom, indexFrom, lineTo, indexTo);
}

void CodeGeeXReceiver::processActionInvokedEvent(const dpf::Event &event)
{
    auto actId = event.property("actionId").toString();
    if (actId == "codegeex_login_default")
        QMetaObject::invokeMethod(CodeGeeXManager::instance(), "login", Qt::QueuedConnection);
    else if (actId == "ai_rag_install")
        QMetaObject::invokeMethod(CodeGeeXManager::instance(), "installConda", Qt::QueuedConnection);
}

void CodeGeeXReceiver::processOpenProjectEvent(const dpf::Event &event)
{
    auto projectPath = event.property("workspace").toString();
    QJsonObject results = CodeGeeXManager::instance()->query(projectPath, "", 1);
    if (results["Chunks"].toArray().size() != 0) // project has generated, update it
        QMetaObject::invokeMethod(CodeGeeXManager::instance(), "generateRag", Qt::QueuedConnection, Q_ARG(const QString &, projectPath));
}

void CodeGeeXReceiver::processSwitchToWidget(const dpf::Event &event)
{
    auto widgetName = event.property("name").toString();
    QMetaObject::invokeMethod(this, [=]() {
        Q_EMIT CodeGeeXCallProxy::instance()->switchToWidget(widgetName);
    });
}

CodeGeeXCallProxy::CodeGeeXCallProxy()
{
}

CodeGeeXCallProxy *CodeGeeXCallProxy::instance()
{
    static CodeGeeXCallProxy proxy;
    return &proxy;
}
